#ifndef __EEExpUtil_H__
#define __EEExpUtil_H__

#include "EEExpMath.h"
#include <maya/MFnMesh.h>
#include <maya/MFloatPoint.h>

#include "../PRide/common/string.h"

#include <vector>
#include <stdio.h>

struct node;

#define WRITESTRING(str, file) fwrite(str, sizeof(char) * strlen(str), 1, file);

enum Classify
{
	LEFT = 1,
	INSIDE = 0,
	RIGHT = -1
};

enum Axis
{
	X = 0,
	Y,
	Z
};

struct vertex
{
	vertex()
	{
		pos			= vector3();
		texcoordA	= vector2();
		texcoordB	= vector2();
		texcoordC	= vector2();

	}
	vertex(float x,float y, float z, float u, float v)
	{
		pos			= vector3(x,y,z);
		texcoordA	= 
		texcoordB	= 
		texcoordC	= vector2(u,v);
	}
	vertex(vector3 pos, vector2 texcoord)
	{
		this->pos		= pos;
		texcoordA	= 
		texcoordB	= 
		texcoordC	= texcoord;
	}
	vertex(MFloatPoint pos, float u, float v)
	{
		this->pos		= vector3(pos.x,pos.y,pos.z);
		texcoordA	= 
		texcoordB	= 
		texcoordC	= vector2(u,v);
	}

	vector3 pos;
	vector3 normal;
	vector2 texcoordA;
	vector2 texcoordB;
	vector2 texcoordC;

	static vertex baseLerp(float t, vertex& A, vertex& B);

	inline void write(FILE* pFile);
};

struct materialData
{
	string shader;
	string decalTexture;
	string normalTexture;
	string auxTexture;
};

struct triangle
{
	vertex A,B,C;

	triangle()
	{
		A = vertex(); 
		B = vertex();
		C = vertex();
	}

	triangle(vertex& A,vertex& B,vertex& C)
	{
		this->A = A; 
		this->B = B;
		this->C = C;
	}
	
	void write(FILE* pFile);
	inline vector3 normal() const;

	static bool split(triangle& tri, plane& splitPlane, triangle& outA, triangle& outB, triangle& outC);

	
};

struct KDTree
{
	static const int MAX_LEAF_TRIANGLES = 3;
	static const int MAX_TREE_DEPTH = 15;

	static int depth;
	static int nodecount;

	static std::vector<node*> treeNodes;

	static Classify classify(plane &classifier, triangle& tri);
	static Classify classify(plane &classifier, vertex& ver);
	static Classify classify(plane &classifier, vector3& vec);

	static bool isPlaneBetween(plane& classifier, vertex& A, vertex& B);
	static bool vertexAtSplit(plane& classifier, vertex& A, vertex& B, vertex& splitPoint);

	static float minPositionOnAxis(Axis splitAxis, std::vector<triangle>* triangles);
	static float maxPositionOnAxis(Axis splitAxis, std::vector<triangle>* triangles);

	static void countClassifications(plane& classifier, int* negativeSideCount, int* positiveSideCount, std::vector<triangle>* triangles);
	static void findOptimalSplitPlane(plane& parentSplitPlane, Axis resultPlaneNormal, std::vector<triangle>* triangles, int itterations = 15);
	static void partionTriangles(plane& parentSplitPlane, std::vector<triangle>* triangles, 
		Axis parentSplitPlaneAxis, node* parent);
};
#endif